package com.itstudy.rpc;

import com.itstudy.common.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: myChannelHandler
 * @Auther: Jerry
 * @Date: 2020/8/18 0:10
 * @Desctiption: TODO
 * @Version: 1.0
 */
public class RpcRegistryHandler extends ChannelInboundHandlerAdapter {

    private List<String> classNames = new ArrayList<>();
    private Map<String, Object> registryMap = new ConcurrentHashMap<>();

    public RpcRegistryHandler() {
        doScanner("com.itstudy.rpc.service");
        doRegistry();
    }

    private void doRegistry() {
        if (classNames.isEmpty()) {return;}
        try {
            // 注册service
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                // 接口名称作为服务名
                Class<?> serviceName = clazz.getInterfaces()[0];
                registryMap.put(serviceName.getName(), clazz.newInstance());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void doScanner(String packageName) {
        URL resource = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
        File file = new File(resource.getFile());
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                doScanner(packageName + "." + f.getName());
            } else {
                classNames.add(packageName + "." + f.getName().replace(".class", ""));
            }
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcRequest rpcRequest = (RpcRequest) msg;
        Object result = new Object();
        if (registryMap.containsKey(rpcRequest.getClassName())) {
            Object service = registryMap.get(rpcRequest.getClassName());
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
            System.out.println("============msg:" + rpcRequest.getClassName());
            result = method.invoke(service, rpcRequest.getParameters());
        }
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }
}
